package analysis.bean;

import common.DateEnum;
import util.TimeUtil;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

public class DateDemension extends Unit {
    public int id;
    public int year;
    public int season;
    public int month;
    public int week;
    public int day;
    public Date Calender = new Date();
    public String type;

    public DateDemension() {
    }

    public DateDemension(int year, int season, int month, int week, int day, Date calender, String type) {
        this.year = year;
        this.season = season;
        this.month = month;
        this.week = week;
        this.day = day;
        Calender = calender;
        this.type = type;
    }

    @Override
    public int compareTo(Unit o) {
        DateDemension other = (DateDemension) o;
        if (this.id != other.id) {
            return this.id - other.id;
        } else {
            if (this.year != other.year) {
                return this.year - other.year;
            } else {
                if (this.season != other.season) {
                    return this.season - other.season;
                } else {
                    if (this.month != other.month) {
                        return this.month - other.month;
                    } else {
                        if (this.week != other.week) {
                            return this.week - other.week;
                        } else {
                            if (this.day != other.day) {
                                return this.day - other.day;
                            } else {
                                if (!this.type.equals(other.type)) {
                                    return this.type.compareTo(other.type);
                                } else {
                                    return 0;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    @Override
    public void write(DataOutput dataOutput) throws IOException {
        dataOutput.writeInt(id);
        dataOutput.writeInt(year);
        dataOutput.writeInt(season);
        dataOutput.writeInt(month);
        dataOutput.writeInt(week);
        dataOutput.writeInt(day);
        dataOutput.writeLong(Calender.getTime());
        dataOutput.writeUTF(type);
    }

    @Override
    public void readFields(DataInput dataInput) throws IOException {
        this.id = dataInput.readInt();
        this.year = dataInput.readInt();
        this.season = dataInput.readInt();
        this.month = dataInput.readInt();
        this.week = dataInput.readInt();
        this.day = dataInput.readInt();
        this.Calender.setTime(dataInput.readLong());
        this.type = dataInput.readUTF();
    }

    public static DateDemension buildDate(long time, DateEnum type) {
        int year = TimeUtil.getDateInfo(time, DateEnum.YEAR);
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        if (type.equals(DateEnum.YEAR)) {
            calendar.setTimeInMillis(time);
            return new DateDemension(year, 0, 0, 0, 1, calendar.getTime(), type.dateType);
        }

        int season = TimeUtil.getDateInfo(time, DateEnum.SEASON);
        if (type.equals(DateEnum.SEASON)) {
            int month = season * 3 - 2;
            calendar.set(year, month - 1, 1);
            return new DateDemension(year, season, month, 0, 1, calendar.getTime(), type.dateType);
        }
        int month = TimeUtil.getDateInfo(time, DateEnum.MONTH);
        if (type.equals(DateEnum.MONTH)) {
            calendar.set(year, month - 1, 1);
            return new DateDemension(year, season, month, 0, 1, calendar.getTime(), type.dateType);
        }
        int week = TimeUtil.getDateInfo(time, DateEnum.WEEK);
        if (type.equals(DateEnum.WEEK)) {
            long firstday = TimeUtil.getFirstDayOfWeek(time);
            year = TimeUtil.getDateInfo(firstday, DateEnum.YEAR);
            season = TimeUtil.getDateInfo(firstday, DateEnum.SEASON);
            month = TimeUtil.getDateInfo(firstday, DateEnum.MONTH);
            int day = TimeUtil.getDateInfo(firstday, DateEnum.DAY);
            calendar.set(year, month - 1, 1);
            return new DateDemension(year, season, month, week, day, calendar.getTime(), type.dateType);
        }
        throw new RuntimeException("Illegal time");
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DateDemension that = (DateDemension) o;
        return id == that.id &&
                year == that.year &&
                season == that.season &&
                month == that.month &&
                week == that.week &&
                day == that.day &&
                Objects.equals(Calender, that.Calender) &&
                Objects.equals(type, that.type);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, year, season, month, week, day, Calender, type);
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getSeason() {
        return season;
    }

    public void setSeason(int season) {
        this.season = season;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public int getWeek() {
        return week;
    }

    public void setWeek(int week) {
        this.week = week;
    }

    public int getDay() {
        return day;
    }

    public void setDay(int day) {
        this.day = day;
    }

    public Date getCalender() {
        return Calender;
    }

    public void setCalender(Date calender) {
        Calender = calender;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}
